Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Node / ReticulumProjects / MeshChatX.git / files / scripts / ci / verify-package-contents.sh

Displaying Raw • Download


scripts/ci/verify-package-contents.sh e41daa5b65e07a5baa1aaad32d97f90482f1cd1c (e41daa5b) Text, 8.34 KB

T8b949e#!/usr/bin/env bash
T8b949e# Fail if release artifacts contain paths that should not ship
T8b949e# (dev trees, duplicate frontend sources, vendor offline caches, etc.).
T8b949e#
T8b949e# Usage:
T8b949e# verify-package-contents.sh frozen [build/exe]
T8b949e# verify-package-contents.sh docker [image:tag]
T8b949e# verify-package-contents.sh wheel [path/to.whl]
T8b949e# verify-package-contents.sh dir [path]
T8b949e# verify-package-contents.sh appimage [path/to.AppImage]
T8b949e# verify-package-contents.sh deb [path/to.deb]
T8b949e# verify-package-contents.sh apk [path/to.apk]
T8b949e#
T8b949e# Env:
T8b949e# PACKAGE_BLOAT_MAX_HITS stop after N hits (default 40)
Tffa657set -euo pipefail

Te6edf3ROOTTff7b72=Ta5d6ff"Tff7b72$(Te6edf3CDPATHTff7b72=Ta5d6ff'' Tffa657cd -- Ta5d6ff"Tff7b72$(dirname Ta5d6ff"Te6edf3$0Ta5d6ff"Tff7b72)Ta5d6ff/../..Ta5d6ff" Tff7b72&& Tffa657pwdTff7b72)Ta5d6ff"
Te6edf3MODETff7b72=Ta5d6ff"Tffd700${Te6edf31Tff7b72:-Tffd700}Ta5d6ff"
Te6edf3TARGETTff7b72=Ta5d6ff"Tffd700${Te6edf32Tff7b72:-Tffd700}Ta5d6ff"
Te6edf3MAX_HITSTff7b72=Ta5d6ff"Tffd700${Te6edf3PACKAGE_BLOAT_MAX_HITSTff7b72:-Te6edf340Tffd700}Ta5d6ff"

usageTff7b72(Tff7b72) Tff7b72{
cat Ta5d6ff<<'EOF' >&2
Usage:
verify-package-contents.sh frozen [build/exe]
verify-package-contents.sh docker [image:tag]
verify-package-contents.sh wheel [file.whl]
verify-package-contents.sh dir [path]
verify-package-contents.sh appimage [file.AppImage]
verify-package-contents.sh deb [file.deb]
verify-package-contents.sh apk [file.apk]
EOF
Tffa657exit T79c0ff2
Tff7b72}

Tff7b72[ -n Ta5d6ff"Te6edf3$MODETa5d6ff" Tff7b72] Tff7b72|| usage

Te6edf3hitsTff7b72=T79c0ff0
Te6edf3hit_linesTff7b72=Tff7b72(Tff7b72)

record_hitTff7b72(Tff7b72) Tff7b72{
Te6edf3hitsTff7b72=Tff7b72$((Te6edf3hits Tff7b72+ T79c0ff1Tff7b72))
Tff7b72if Tff7b72[ Ta5d6ff"Tffd700${#Te6edf3hit_linesTb4b4b4[@]Tffd700}Ta5d6ff" -lt Ta5d6ff"Te6edf3$MAX_HITSTa5d6ff" Tff7b72]Tb4b4b4; Tff7b72then
Te6edf3hit_linesTff7b72+=Tff7b72(Ta5d6ff"Te6edf3$1Ta5d6ff"Tff7b72)
Tff7b72fi
Tff7b72}

T8b949e# Shared denylist patterns (grep -E against relative paths).
T8b949e# Bytecode (__pycache__) is denied for frozen/wheel/dir but not docker:
T8b949e# Dockerfiles run compileall on purpose for faster cold start.
T8b949e#
T8b949e# Do not use a bare /(^|/)android(/|$)/ pattern: LXST ships
T8b949e# LXST/Platforms/android for mobile hosts. That path must remain allowed in
T8b949e# APKs and must not false-fail Docker scans of site-packages.
Te6edf3COMMON_DENY_RETff7b72=Ta5d6ff'(^|/)\.git(/|$)|(^|/)node_modules(/|$)|(^|/)\.pnpm-store(/|$)|(^|/)\.venv(/|$)|(^|/)vendor/offline(/|$)|(^|/)vendor/lxmfy/tests(/|$)|(^|/)vendor/lxmfy/docs(/|$)|(^|/)vendor/lxmfy/docker(/|$)|(^|/)vendor/rns_filesync/tests(/|$)|(^|/)vendor/rns_filesync/docs(/|$)|(^|/)vendor/rns_filesync/docker(/|$)|(^|/)vendor/rns_filesync/packaging(/|$)|(^|/)vendor/rns_filesync/sideband(/|$)|(^|/)vendor/rns_filesync/man(/|$)|(^|/)vendor/rns_filesync/scripts(/|$)|(^|/)\.github(/|$)|(^|/)docs/agents(/|$)|(^|/)screenshots(/|$)|(^|/)\.pytest_cache(/|$)|(^|/)mutants(/|$)|(^|/)coverage(/|$)'

Te6edf3BYTECODE_DENY_RETff7b72=Ta5d6ff'(^|/)__pycache__(/|$)'

T8b949e# MeshChatX Android app sources (gradle/app tree), not LXST.Platforms.android.
Te6edf3ANDROID_APP_DENY_RETff7b72=Ta5d6ff'(^|/)android/(app|gradle)(/|$)|(^|/)android/[^/]+\.(gradle|kts|properties)$|(^)android(/|$)'

Te6edf3FROZEN_DENY_RETff7b72=Ta5d6ff"Tffd700${Te6edf3COMMON_DENY_RETffd700}Ta5d6ff|Tffd700${Te6edf3BYTECODE_DENY_RETffd700}Ta5d6ff|(^|/)lib/meshchatx/public(/|$Ta5d6ff)|(^|/)lib/meshchatx/src/frontend/.+\.vue$Ta5d6ff|(^|/)lib/meshchatx/src/frontend/.+\.css$Ta5d6ff|(^|/)lib/setuptools(/|$Ta5d6ff)|(^|/)lib/pydoc_data(/|$Ta5d6ff)|(^|/)lib/numpy/.*/tests(/|$Ta5d6ff)|(^|/)lib/numpy/tests(/|$Ta5d6ff)Ta5d6ff"

Te6edf3DOCKER_DENY_RETff7b72=Ta5d6ff"Tffd700${Te6edf3COMMON_DENY_RETffd700}Ta5d6ff|Tffd700${Te6edf3ANDROID_APP_DENY_RETffd700}Ta5d6ff|(^|/)meshchatx/src/frontend/.+\.vue$Ta5d6ff|(^|/)meshchatx/src/frontend/.+\.css$Ta5d6ff|(^|/)tests(/|$Ta5d6ff)|(^|/)electron(/|$Ta5d6ff)|(^|/)LXST/Platforms/android(/|$Ta5d6ff)Ta5d6ff"

Te6edf3WHEEL_DENY_RETff7b72=Ta5d6ff"Tffd700${Te6edf3COMMON_DENY_RETffd700}Ta5d6ff|Tffd700${Te6edf3BYTECODE_DENY_RETffd700}Ta5d6ff|(^|/)meshchatx/src/frontend/.+\.vue$Ta5d6ff|(^|/)meshchatx/src/frontend/.+\.css$Ta5d6ff|(^|/)tests(/|$Ta5d6ff)Ta5d6ff"

Te6edf3APK_DENY_RETff7b72=Ta5d6ff"Tffd700${Te6edf3COMMON_DENY_RETffd700}Ta5d6ff|Tffd700${Te6edf3BYTECODE_DENY_RETffd700}Ta5d6ff|Tffd700${Te6edf3ANDROID_APP_DENY_RETffd700}Ta5d6ff|(^|/)tests(/|$Ta5d6ff)|(^|/)electron(/|$Ta5d6ff)|(^|/)\.github(/|$Ta5d6ff)Ta5d6ff"

Te6edf3DIR_DENY_RETff7b72=Ta5d6ff"Tffd700${Te6edf3COMMON_DENY_RETffd700}Ta5d6ff|Tffd700${Te6edf3BYTECODE_DENY_RETffd700}Ta5d6ff"

T8b949e# Read relative paths from stdin. Must not run in a pipe subshell so hits persist.
scan_path_listTff7b72(Tff7b72) Tff7b72{
Te6edf3deny_reTff7b72=Ta5d6ff"Te6edf3$1Ta5d6ff"
Tff7b72while Te6edf3IFSTff7b72= Tffa657read -r rel Tff7b72|| Tff7b72[ -n Ta5d6ff"Tffd700${Te6edf3relTff7b72:-Tffd700}Ta5d6ff" Tff7b72]Tb4b4b4; Tff7b72do
Tff7b72[ -n Ta5d6ff"Te6edf3$relTa5d6ff" Tff7b72] Tff7b72|| Tff7b72continue
Te6edf3relTff7b72=Ta5d6ff"Tffd700${Te6edf3relTb4b4b4#./Tffd700}Ta5d6ff"
Tff7b72case Ta5d6ff"Te6edf3$relTa5d6ff" Tff7b72in
Ta5d6ff""Tff7b72) Tff7b72continue Tb4b4b4;Tb4b4b4;
Tff7b72esac
Tff7b72if Tffa657printf Ta5d6ff'%s\n' Ta5d6ff"Te6edf3$relTa5d6ff" Tb4b4b4| grep -Eq Ta5d6ff"Te6edf3$deny_reTa5d6ff"Tb4b4b4; Tff7b72then
record_hit Ta5d6ff"Te6edf3$relTa5d6ff"
Tff7b72fi
Tff7b72done
Tff7b72}

resolve_frozen_rootTff7b72(Tff7b72) Tff7b72{
Te6edf3baseTff7b72=Ta5d6ff"Tffd700${Te6edf31Tff7b72:-Tffd700}Ta5d6ff"
Tff7b72if Tff7b72[ -z Ta5d6ff"Te6edf3$baseTa5d6ff" Tff7b72]Tb4b4b4; Tff7b72then
Te6edf3baseTff7b72=Ta5d6ff"Te6edf3$ROOTTa5d6ff/build/exeTa5d6ff"
Tff7b72fi
Tff7b72if Tff7b72[ ! -d Ta5d6ff"Te6edf3$baseTa5d6ff" Tff7b72]Tb4b4b4; Tff7b72then
Tffa657echo Ta5d6ff"Ta5d6ffverify-package-contents.sh: frozen root missing: Te6edf3$baseTa5d6ff" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72fi
Tff7b72if Tff7b72[ -d Ta5d6ff"Te6edf3$baseTa5d6ff/libTa5d6ff" Tff7b72]Tb4b4b4; Tff7b72then
Tffa657printf Ta5d6ff'%s\n' Ta5d6ff"Te6edf3$baseTa5d6ff"
Tff7b72return T79c0ff0
Tff7b72fi
Tff7b72for sub Tff7b72in Ta5d6ff"Te6edf3$baseTa5d6ff"/*Tb4b4b4; Tff7b72do
Tff7b72if Tff7b72[ -d Ta5d6ff"Te6edf3$subTa5d6ff/libTa5d6ff" Tff7b72]Tb4b4b4; Tff7b72then
Tffa657printf Ta5d6ff'%s\n' Ta5d6ff"Te6edf3$subTa5d6ff"
Tff7b72return T79c0ff0
Tff7b72fi
Tff7b72done
Tffa657echo Ta5d6ff"Ta5d6ffverify-package-contents.sh: no lib/ under Te6edf3$baseTa5d6ff" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72}

scan_directory_treeTff7b72(Tff7b72) Tff7b72{
Te6edf3rootTff7b72=Ta5d6ff"Te6edf3$1Ta5d6ff"
Te6edf3deny_reTff7b72=Ta5d6ff"Te6edf3$2Ta5d6ff"
T8b949e# Process substitution keeps scan_path_list in this shell (hits accumulate).
scan_path_list Ta5d6ff"Te6edf3$deny_reTa5d6ff" < <Tff7b72(
Te6edf3CDPATHTff7b72=Ta5d6ff'' Tffa657cd -- Ta5d6ff"Te6edf3$rootTa5d6ff" Tff7b72|| Tffa657exit T79c0ff1
find . -print T79c0ff2>/dev/null Tb4b4b4| sed Ta5d6ff's|^\./||'
Tff7b72)
Tff7b72}

scan_archive_listingTff7b72(Tff7b72) Tff7b72{
Te6edf3archiveTff7b72=Ta5d6ff"Te6edf3$1Ta5d6ff"
Te6edf3deny_reTff7b72=Ta5d6ff"Te6edf3$2Ta5d6ff"
Tff7b72if Tffa657command -v unzip >/dev/null T79c0ff2>Tb4b4b4&T79c0ff1Tb4b4b4; Tff7b72then
scan_path_list Ta5d6ff"Te6edf3$deny_reTa5d6ff" < <Tff7b72(unzip -Z1 Ta5d6ff"Te6edf3$archiveTa5d6ff" T79c0ff2>/dev/nullTff7b72)
Tff7b72return T79c0ff0
Tff7b72fi
Tffa657echo Ta5d6ff"Ta5d6ffverify-package-contents.sh: unzip required to inspect Te6edf3$archiveTa5d6ff" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72}

scan_frozenTff7b72(Tff7b72) Tff7b72{
Te6edf3rootTff7b72=Ta5d6ff"Tff7b72$(resolve_frozen_root Ta5d6ff"Tffd700${Te6edf3TARGETTff7b72:-Tffd700}Ta5d6ff"Tff7b72)Ta5d6ff"
Tffa657echo Ta5d6ff"Ta5d6ffverify-package-contents.sh: scanning frozen tree Te6edf3$rootTa5d6ff"
scan_directory_tree Ta5d6ff"Te6edf3$rootTa5d6ff" Ta5d6ff"Te6edf3$FROZEN_DENY_RETa5d6ff"
Tff7b72}

scan_dirTff7b72(Tff7b72) Tff7b72{
Te6edf3rootTff7b72=Ta5d6ff"Tffd700${Te6edf3TARGETTff7b72:-Tffd700}Ta5d6ff"
Tff7b72[ -n Ta5d6ff"Te6edf3$rootTa5d6ff" Tff7b72] Tff7b72|| usage
Tff7b72[ -d Ta5d6ff"Te6edf3$rootTa5d6ff" Tff7b72] Tff7b72|| Tff7b72{
Tffa657echo Ta5d6ff"Ta5d6ffverify-package-contents.sh: missing dir Te6edf3$rootTa5d6ff" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72}
Tffa657echo Ta5d6ff"Ta5d6ffverify-package-contents.sh: scanning dir Te6edf3$rootTa5d6ff"
scan_directory_tree Ta5d6ff"Te6edf3$rootTa5d6ff" Ta5d6ff"Te6edf3$DIR_DENY_RETa5d6ff"
Tff7b72}

scan_wheelTff7b72(Tff7b72) Tff7b72{
Te6edf3whlTff7b72=Ta5d6ff"Tffd700${Te6edf3TARGETTff7b72:-Tffd700}Ta5d6ff"
Tff7b72if Tff7b72[ -z Ta5d6ff"Te6edf3$whlTa5d6ff" Tff7b72]Tb4b4b4; Tff7b72then
Te6edf3whlTff7b72=Ta5d6ff"Tff7b72$(find Ta5d6ff"Te6edf3$ROOTTa5d6ff/python-distTa5d6ff" -maxdepth T79c0ff1 -type f -name Ta5d6ff'*.whl' -print T79c0ff2>/dev/null Tb4b4b4| head -n T79c0ff1 Tff7b72|| Tffa657trueTff7b72)Ta5d6ff"
Tff7b72fi
Tff7b72[ -n Ta5d6ff"Te6edf3$whlTa5d6ff" Tff7b72] Tff7b72&& Tff7b72[ -f Ta5d6ff"Te6edf3$whlTa5d6ff" Tff7b72] Tff7b72|| Tff7b72{
Tffa657echo Ta5d6ff"verify-package-contents.sh: wheel not found" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72}
Tffa657echo Ta5d6ff"Ta5d6ffverify-package-contents.sh: scanning wheel Te6edf3$whlTa5d6ff"
scan_archive_listing Ta5d6ff"Te6edf3$whlTa5d6ff" Ta5d6ff"Te6edf3$WHEEL_DENY_RETa5d6ff"
Tff7b72}

scan_apkTff7b72(Tff7b72) Tff7b72{
Te6edf3apkTff7b72=Ta5d6ff"Tffd700${Te6edf3TARGETTff7b72:-Tffd700}Ta5d6ff"
Tff7b72[ -n Ta5d6ff"Te6edf3$apkTa5d6ff" Tff7b72] Tff7b72&& Tff7b72[ -f Ta5d6ff"Te6edf3$apkTa5d6ff" Tff7b72] Tff7b72|| Tff7b72{
Tffa657echo Ta5d6ff"verify-package-contents.sh: apk not found" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72}
Tffa657echo Ta5d6ff"Ta5d6ffverify-package-contents.sh: scanning apk Te6edf3$apkTa5d6ff"
scan_archive_listing Ta5d6ff"Te6edf3$apkTa5d6ff" Ta5d6ff"Te6edf3$APK_DENY_RETa5d6ff"
Tff7b72}

scan_debTff7b72(Tff7b72) Tff7b72{
Te6edf3debTff7b72=Ta5d6ff"Tffd700${Te6edf3TARGETTff7b72:-Tffd700}Ta5d6ff"
Tff7b72[ -n Ta5d6ff"Te6edf3$debTa5d6ff" Tff7b72] Tff7b72&& Tff7b72[ -f Ta5d6ff"Te6edf3$debTa5d6ff" Tff7b72] Tff7b72|| Tff7b72{
Tffa657echo Ta5d6ff"verify-package-contents.sh: deb not found" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72}
Te6edf3tmpTff7b72=Ta5d6ff"Tff7b72$(mktemp -d Ta5d6ff"Tffd700${Te6edf3TMPDIRTff7b72:-Tb4b4b4/tmpTffd700}Ta5d6ff/pkg-bloat-deb.XXXXXXTa5d6ff"Tff7b72)Ta5d6ff"
Tffa657trap Ta5d6ff'rm -rf "$tmp"' EXIT INT
Tffa657echo Ta5d6ff"Ta5d6ffverify-package-contents.sh: extracting deb Te6edf3$debTa5d6ff"
dpkg-deb -x Ta5d6ff"Te6edf3$debTa5d6ff" Ta5d6ff"Te6edf3$tmpTa5d6ff"
scan_directory_tree Ta5d6ff"Te6edf3$tmpTa5d6ff" Ta5d6ff"Te6edf3$FROZEN_DENY_RETa5d6ff"
Tff7b72}

scan_appimageTff7b72(Tff7b72) Tff7b72{
Te6edf3aiTff7b72=Ta5d6ff"Tffd700${Te6edf3TARGETTff7b72:-Tffd700}Ta5d6ff"
Tff7b72[ -n Ta5d6ff"Te6edf3$aiTa5d6ff" Tff7b72] Tff7b72&& Tff7b72[ -f Ta5d6ff"Te6edf3$aiTa5d6ff" Tff7b72] Tff7b72|| Tff7b72{
Tffa657echo Ta5d6ff"verify-package-contents.sh: AppImage not found" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72}
Te6edf3tmpTff7b72=Ta5d6ff"Tff7b72$(mktemp -d Ta5d6ff"Tffd700${Te6edf3TMPDIRTff7b72:-Tb4b4b4/tmpTffd700}Ta5d6ff/pkg-bloat-ai.XXXXXXTa5d6ff"Tff7b72)Ta5d6ff"
Tffa657trap Ta5d6ff'rm -rf "$tmp"' EXIT INT
Tffa657echo Ta5d6ff"Ta5d6ffverify-package-contents.sh: extracting AppImage Te6edf3$aiTa5d6ff"
chmod +x Ta5d6ff"Te6edf3$aiTa5d6ff" Tff7b72|| Tffa657true
Tff7b72(
Te6edf3CDPATHTff7b72=Ta5d6ff'' Tffa657cd -- Ta5d6ff"Te6edf3$tmpTa5d6ff"
Ta5d6ff"Te6edf3$aiTa5d6ff" --appimage-extract >/dev/null
Tff7b72)
scan_directory_tree Ta5d6ff"Te6edf3$tmpTa5d6ff/squashfs-rootTa5d6ff" Ta5d6ff"Te6edf3$FROZEN_DENY_RETa5d6ff"
Tff7b72}

scan_dockerTff7b72(Tff7b72) Tff7b72{
Te6edf3imageTff7b72=Ta5d6ff"Tffd700${Te6edf3TARGETTff7b72:-Tffd700}Ta5d6ff"
Tff7b72[ -n Ta5d6ff"Te6edf3$imageTa5d6ff" Tff7b72] Tff7b72|| Tff7b72{
Tffa657echo Ta5d6ff"verify-package-contents.sh: docker image tag required" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72}
Tff7b72if ! Tffa657command -v docker >/dev/null T79c0ff2>Tb4b4b4&T79c0ff1Tb4b4b4; Tff7b72then
Tffa657echo Ta5d6ff"verify-package-contents.sh: docker not available" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72fi
Tffa657echo Ta5d6ff"Ta5d6ffverify-package-contents.sh: scanning docker image Te6edf3$imageTa5d6ff (/opt/venv)Ta5d6ff"
T8b949e# Use python (always present) so Alpine and Chainguard/hardened images both work.
T8b949e# Emit paths relative to /opt/venv or /app so denylist matches cleanly.
Te6edf3listTff7b72=Ta5d6ff"Tff7b72$(
docker run --rm --user T79c0ff0 --entrypoint python Ta5d6ff"Te6edf3$imageTa5d6ff" -c Ta5d6ff'
import os
roots = [p for p in ("/opt/venv", "/app") if os.path.isdir(p)]
if not roots:
roots = ["/"]
skip_top = {"proc", "sys", "dev", "tmp", "run"}
for root in roots:
for dirpath, dirnames, filenames in os.walk(root):
if root == "/":
if dirpath == "/":
dirnames[:] = [d for d in dirnames if d not in skip_top]
rel_dir = dirpath.lstrip("/") or "."
elif dirpath == root:
rel_dir = "."
else:
rel_dir = dirpath[len(root) + 1 :]
print(rel_dir)
for name in filenames:
if rel_dir == ".":
print(name)
else:
print(rel_dir + "/" + name)
' T79c0ff2>/dev/null Tff7b72|| Tffa657true
Tff7b72)Ta5d6ff"
Tff7b72if Tff7b72[ -z Ta5d6ff"Te6edf3$listTa5d6ff" Tff7b72]Tb4b4b4; Tff7b72then
Tffa657echo Ta5d6ff"Ta5d6ffverify-package-contents.sh: could not list files in Te6edf3$imageTa5d6ff" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72fi
scan_path_list Ta5d6ff"Te6edf3$DOCKER_DENY_RETa5d6ff" Tff7b72<<<Ta5d6ff"Te6edf3$listTa5d6ff"
Tff7b72}

Tff7b72case Ta5d6ff"Te6edf3$MODETa5d6ff" Tff7b72in
frozenTff7b72)
scan_frozen
Tb4b4b4;Tb4b4b4;
dirTff7b72)
scan_dir
Tb4b4b4;Tb4b4b4;
wheelTff7b72)
scan_wheel
Tb4b4b4;Tb4b4b4;
apkTff7b72)
scan_apk
Tb4b4b4;Tb4b4b4;
debTff7b72)
scan_deb
Tb4b4b4;Tb4b4b4;
appimageTff7b72)
scan_appimage
Tb4b4b4;Tb4b4b4;
dockerTff7b72)
scan_docker
Tb4b4b4;Tb4b4b4;
*Tff7b72)
usage
Tb4b4b4;Tb4b4b4;
Tff7b72esac

Tff7b72if Tff7b72[ Ta5d6ff"Te6edf3$hitsTa5d6ff" -gt T79c0ff0 Tff7b72]Tb4b4b4; Tff7b72then
Te6edf3shownTff7b72=Ta5d6ff"Tffd700${#Te6edf3hit_linesTb4b4b4[@]Tffd700}Ta5d6ff"
Tffa657echo Ta5d6ff"Ta5d6ffverify-package-contents.sh: FAIL (Te6edf3$hitsTa5d6ff forbidden path(s), showing Te6edf3$shownTa5d6ff)Ta5d6ff" >Tb4b4b4&T79c0ff2
Tff7b72for line Tff7b72in Ta5d6ff"Tffd700${Te6edf3hit_linesTb4b4b4[@]Tffd700}Ta5d6ff"Tb4b4b4; Tff7b72do
Tffa657echo Ta5d6ff"Ta5d6ff - Te6edf3$lineTa5d6ff" >Tb4b4b4&T79c0ff2
Tff7b72done
Tffa657exit T79c0ff1
Tff7b72fi

Tffa657echo Ta5d6ff"Ta5d6ffverify-package-contents.sh: OK (Te6edf3$MODETa5d6ff)Ta5d6ff"


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────